package com.cskaoyan.javase.oop2._1extends._9override;

/**
 * 方法的重写/方法的覆盖
 * 如果父子类中出现同名的成员方法,那么使用"对象名点"调用成员方法,结果是什么样的呢?
 * 显然用子类引用指向子类对象,然后用对象名点调用同名成员方法,结果是子类的行为
 * 那么:
 *      这种体现出子类行为的特点,是隐藏还是覆盖呢?
 *      通过一个父类中调用同名方法的一个方法,我们发现父类中的方法,无法去调用到,应该是方法被覆盖了
 *
 * 接下来重点研究"对象名点成员方法"的访问机制,主要是以下两点:
 *       1.访问范围,即能够访问什么
 *       2.调用结果,即方法调用的行为到底是什么
 *  在本案例三个类中,创建对象,用对象名点访问成员变量有三种方式:
 *       1.创建父类Phone对象,用父类引用Phone接收
 *       2.创建子类XiaoMiPhone对象,用子类引用XiaoMiPhone接收
 *       3.创建子类XiaoMiPhone对象,用父类引用Phone接收
 *
 * 首先研究访问范围:
 *      经过测试,对象名点成员方法的访问范围和对象名点访问成员变量的访问范围是一样的
 *      都只需要看引用的数据类型即可
 * 接下来研究方法调用的结果:
 *      经过测试,对象名点成员方法的调用结果是根据对象的具体类型来决定的
 *      如果子类对象,那么调用结果就要去子类中查找该方法的实现.
 *      如果子类重写了父类中的实现,那就要体现出子类的行为
 *
 * 综上所述:
 *      对象名点访问成员方法
 *      访问范围仍然是根据引用的数据类型来决定的
 *      调用的结果要根据对象的具体类型而定.
 *
 *
 * 注意事项:
 *      1.方法不像变量一样需要开辟空间存储它,在没有调用方法时,方法不过是一系列的指令合集
 *      在类加载时,被存放在方法区中
 *      不同类的方法存在不同的区域
 *      所以,方法的覆盖不是物理意义上的覆盖,而是因为对象名点成员方法访问机制体现出了方法的覆盖
 *      那么有没有办法在子类中去访问父类中的同名方法呢?
 *      使用super关键字,但是注意要受访问权限限制.
 *
 *
 *      2.实际开发中,我们多数情况下都是调用方法来实现功能,很少会直接访问成员变量
 *          所以对象名点成员方法是非常重要的,方法的覆盖/方法重写在Java也是非常重要的语法
 *          它有自身比较独特的语法
 *          接下来我们重点学习方法的覆盖的语法.
 *
 *
 * @since 16:08
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*IPhone p = new IPhone();
        p.call();
        p.invokeCallFather();*/

        // 三种创建对象的方式
        Phone p = new Phone();
        // p.call();
        // p.invokeCallFather();
        XiaoMiPhone xp = new XiaoMiPhone();
        xp.invokeFatherCall();
        // xp.call();
        // xp.invokeCallFather();
        Phone pm = new XiaoMiPhone();
        // pm.call();
        // pm.invokeCallFather();

    }
}

class Phone {
    public void call() {
        System.out.println("打电话");
    }

    public void invokeCallFather(){
        call();
    }
    public void testFather() {
    }
}

class IPhone extends Phone {
    public void call() {
        System.out.println("嘿Siri,帮我打电话.");
    }
}

class XiaoMiPhone extends Phone {
    public void call() {
        System.out.println("小爱同学,帮我打电话.");
    }

    public void testSon() {
    }

    public void invokeFatherCall(){
        super.call();
    }

}